#ifndef _KLAS_NODE_HPP_
#define _KLAS_NODE_HPP_

#include "../include/Rectangle.hpp"
#include "../include/Color.hpp"
#include <vector>
#include <list>
using namespace std;

namespace klas
{
  struct Projection
	{
	  Real min, max;
	  
	  Projection(Real min, Real max);
	  bool intersects(const Projection& other);
  };
  
  struct Polygon
  {
    Polygon(); // doesn't do anything
    Polygon(const vector<Vector2<Real> >& pts);
    
    vector<Vector2<Real> > pts;
    list<Vector2<Real> > edges;
    
    Projection projectToAxis(const Vector2<Real>& axis);
    
    bool intersects(Polygon other);
  };
  
  
	//! The node represents an object inside the world.
	/*! This is a pure virtual class.  It's been designed to be easily extendable. */
	class Node
	{
		public:
			
			//! Ctor.
			Node();
			
			//! Dtor.
			virtual ~Node();
					
			//! Changes the node's rectangle.
			/*! \param rect The new rectangle. */
			void setRect(const Rectangle<Real>& rect);
			
			//! Changes the position of the node.
			/*! \param pos The node's new position. */
			void setPos(const Vector2<Real>& pos);
			
			//! Gets the position of the node.
			/*! \return The position of the node. */
			Vector2<Real> getPos() const;
			
			//! Adds qty to the position of the node.
			/*! For example, pos (2, 0) translated by (5, -12) results in (7, -12)
			    \param qty The amount to move the node by. */
			void translate(const Vector2<Real>& qty);
			
			//! Gets the Node's rectangle.
			/*! \return The rectangle of the node. */
			Rectangle<Real> getRect() const;
			
			//! Gets the previous position of the node.
			/*! \return The position of the node before the last setRect() call.
					\sa setRect(const Rectangle& rect) */
			Rectangle<Real> getPrevRect() const;
			
			//! Changes the rotation of the node.
			/*! \param rot The new rotation of the node.
					\param radians Is the rotation in radians or degrees? */
			void setRot(Real rot, bool radians=false);
			
			//! Gets the node's rotation.
			/*! \return The rotation of the node. */
			Real getRot() const;
			
			//! Changes the scale of the node to a ratio of its texture size.
			/*! \param scale The new scale of the node. */
			void setScale(Real scale);
			
			//! Changes the scale of the node to a specific size.
			/*! Only the "width" is considered when setting the scale.
			    \param dim The new dimensions. */
			void setScale(const Vector2<Real>& dim);
			
			//! Gets the node's scale.
			/*! \return The scale of the node. */
			Real getScale() const;
			
			//! Changes the minimum and maximum position of the node.
			/*! The nodes position must lie between min and max.
			    \param min The minimum position. (ie: (0, 0))
			    \param max The maximum position. (ie: (100, 100)) */
			void setMinMaxPos(const Vector2<Real>& min, const Vector2<Real>& max);
			
			//! Changes the ID of the node.
			/*! \param ID The new ID of the node. */
			void setID(iReal ID);
			
			//! Gets the ID of the node.
			/*! \return The ID of the node. */
			iReal getID() const;
			
			//! Sets if the node should render.
			/*! \param val This value is true if the node will be displayed. */
			void shouldRender(bool val);
			
			//! Gets if the node is being rendered.
			/*! \return True if the node is being rendered. */
			bool shouldRender() const;
			
			//! Sets the "base" color of the node.
			/*! The base color is effectively the color of shading that is applied to the node.
			    \param col The base color to use. */
			void setBaseColor(const Color& col);
			
			//! Gets the base color of the node.
			/*! \return The base color of the node. */
			Color getBaseColor() const;
			
			//! Gets a deep copy of the node.
			/*! \return A deep copy of the node.  You have to call delete on the new node. */
			virtual Node* getDeepCopy() = 0;
			
			//! Gets what type of this node is.  IE: Texture, Primitive, etc.
			/*! \return The type of the node. */			
			virtual iReal getNodeType() const = 0;
			
			//! Renders the node.
			virtual void render(const Rectangle<Real>& camera) = 0;
				
			//! Types of nodes.
			enum NodeTypes {
				TEXTURE,
				PRIMITIVE,
				FONT
			};
			
			//! Returns the polygon of the node.
			Polygon getPolygon() const;
			
		protected:
			
			//! The node's polygon
			Polygon m_polygon;
			
			//! The base color of the polygon.  Defaults to {1, 1, 1, 1}
			Color m_baseColor;
			
			// Rebuilds the node's polygon
			void constructPolygon();
			
			//! The current rectangle of the node.
			Rectangle<Real> m_rect,
			
			//! The previous rectangle of the node.
								m_prevRect;
								
			//! The node's rotation.
			Real m_rot,
			
			//! The node's scale.
					 m_scale;
					 
			//! The minimum position of the node. 
			/*! For example, if this is (0, 0), then this node cannot have negative 
			    coordinates. */
			Vector2<Real> m_minPos,
			
			//! The minimum position of the node. 
			/*! For example, if this is (0, 0), then this node cannot have positive 
			    coordinates. */
			              m_maxPos;
			
			//! The ID of the node.
			iReal m_ID;
			
			//! Should the node render?
			bool m_shouldRender;
	};
}

#endif
